#include "wordframe.h"

#include "DictEngin.h"
#include "FlyWidget.h"
#include "LookupWidget.h"
#include "MSettings.h"
#include "SearchOverlay.h"
#include "qhotkey.h"
#include "ui_wordframe.h"
#include "boundaryswitchbase.h"
#include "bezierwave.h"
#include "dynamicbackgroundpure.h"
#include "dynamicbackgroundgradient.h"
#include "checkbox1.h"


#define KNOWN "known.txt"
#define DICTEN "dicts/en"

WordFrame::WordFrame(QWidget* parent) : QFrame(parent), ui(new Ui::WordFrame) {
    ui->setupUi(this);
    m_tidL1 = m_tidL2 = m_tidL3 = -1;
    m_lookup = new LookupWidget;
    m_enTimer = new QTimer(this);
    connect(m_enTimer, &QTimer::timeout, this, [this]() {
        ui->lb_idx->setNum(m_idx);
        genWord();
    });

    ui->stackedWidget->setCurrentWidget(ui->main_page);
    connect(ui->pb_update, &QPushButton::clicked, this,
            [this]() { ui->stackedWidget->setCurrentWidget(ui->dict_page); });
    connect(ui->pb_back, &QPushButton::clicked, this,
            [this]() { ui->stackedWidget->setCurrentWidget(ui->main_page); });

    initCoca();
    initCsh();
    initDicts();
    getUnknownWord("");

    dm_bg = new DynamicBackgroundGradient(this);

    //    dm_bg->setColor(QColor(255, 0, 0), QColor(0, 255, 0));
    //    dm_bg->setColor(QColor(255, 0, 0), QColor(128, 0, 0), QColor(0, 255, 0), QColor(0, 128, 0));

    dm_bg->setInterval(1000);
    //    dm_bg->setHorizone(true);
    //    dm_bg->setColor2(Qt::red, Qt::red);
    dm_bg->showAni();
    connect(dm_bg, SIGNAL(signalRedraw()), this, SLOT(update()));

    // 搜索覆盖层
    m_overlay = new SearchOverlay(m_mdxEngin, nullptr);
    connect(m_overlay, &SearchOverlay::searchSubmitted, this,
            [this](const QString& text) {
                if (!m_mdxEngin) return;
                QString html = m_mdxEngin->query(text);
                QPoint pos = m_overlay->geometry().bottomLeft() + QPoint(0, 10);
                m_lookup->moveAndExplain(html, Qt::LeftButton, pos);
            });

    // 注册全局快捷键
    m_popupHotkey = new QHotkey(QKeySequence("ctrl+p"), true, this);
    connect(m_popupHotkey, &QHotkey::activated, this,
            [this]() { m_overlay->toggle(); });
}

void WordFrame::updateDicts() {
    QStringList files;
    QFile json("./user.json");
    json.open(QIODevice::ReadOnly);
    QJsonDocument doc = QJsonDocument::fromJson(json.readAll());
    json.close();
    if (doc.isObject()) {
        auto obj = doc.object();
        if (!obj.contains("dicts")) {
            return;
        }
        auto dicts = obj.value("dicts");
        if (!dicts.isArray()) return;
        auto arrs = dicts.toArray();
        for (auto dict : arrs) {
            QFileInfo file(dict.toString());
            if (file.exists()) {
                files.append(file.absoluteFilePath());
            }
        }
    } else {
        qDebug() << "user.json配置不正常";
    }
    // m_mdxEngin->updateDict(files);
}

void WordFrame::initDicts() {
    m_mdxEngin = new MdxEngin;
    connect(ui->lv_dicts, &QListWidget::itemDoubleClicked, this,
            [this](QListWidgetItem* item) {
                if (!item) return;
                auto info =
                    m_mdxEngin->metaInfo(item->data(Qt::UserRole).toString());
                ui->lb_info->setText(info);
            });
    ui->lv_dicts->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->lv_dicts, &QListWidget::customContextMenuRequested, this,
            [this](QPoint pos) {
                // 1. 找到被点击的 Item
                QListWidgetItem* item = ui->lv_dicts->itemAt(pos);
                if (item) {
                    // 2. 创建 QMenu
                    QMenu menu(this);

                    // 3. 创建 QAction（菜单项）
                    QAction* deleteAction = new QAction(tr("删除项目"), this);
                    QAction* editAction = new QAction(tr("编辑项目"), this);
                    connect(deleteAction, &QAction::triggered, this,
                            [this, item](bool trigger) {
                                if (item) {
                                    QString file =
                                        item->data(Qt::UserRole).toString();
                                    auto ok = m_mdxEngin->delDict(file);
                                    qDebug() << "delete:::" << file << ok;
                                    if (ok) {
                                        delete ui->lv_dicts->takeItem(
                                            ui->lv_dicts->row(item));
                                        auto dicts = MSettings::value(
                                                         DICTEN, QStringList{})
                                                         .removeAll(file);
                                        MSettings::setValue(DICTEN, dicts);
                                    }
                                }
                            });

                    // 4. 将 Action 添加到 Menu
                    menu.addAction(deleteAction);
                    menu.addAction(editAction);
                    // 6. 显示菜单 (使用 mapToGlobal 将 widget
                    // 坐标转换为屏幕坐标)
                    menu.exec(ui->lv_dicts->mapToGlobal(pos));
                }
            });
    connect(ui->pb_add, &QPushButton::clicked, this, [this]() {
        QFileDialog* dlg = new QFileDialog(this, "字典", "", "*.mdx");
        QStringList files;
        if (dlg->exec()) {
            files = dlg->selectedFiles();
            qDebug() << files;
            for (auto& file : files) {
                bool loaded = m_mdxEngin->addDict(file);
                if (loaded) {
                    QStringList dicts = MSettings::value(DICTEN, QStringList{});
                    dicts.append(file);
                    MSettings::setValue(DICTEN, dicts);
                    QFileInfo info(file);
                    if (info.isFile()) file = info.fileName();
                    QListWidgetItem* item =
                        new QListWidgetItem(file, ui->lv_dicts);
                    item->setData(Qt::UserRole, info.absoluteFilePath());
                }
            }
        }
    });

    QStringList dicts = MSettings::value(DICTEN, QStringList{});
    for (auto& dict : dicts) {
        QFileInfo info(dict);
        if (info.isFile()) {
            bool loaded = m_mdxEngin->addDict(dict);
            if (loaded) {
                dict = info.fileName();
                QListWidgetItem* item = new QListWidgetItem(dict, ui->lv_dicts);
                item->setData(Qt::UserRole, info.absoluteFilePath());
                // ui->lv_dicts->addItem(item);
            }
        }
    }
}

void WordFrame::initCoca() {
        BoundarySwitchBase* sb = new BoundarySwitchBase(this);
    sb->setMaximumSize(QSize(60,30));
    ui->lo_gb->insertWidget(0, sb);
    connect(ui->sl_speed, &QSlider::sliderReleased, this, [=]() {
        ui->lb_speed->setNum(ui->sl_speed->value());
        if(!sb->isChecked()) return;
        m_enTimer->start(ui->sl_speed->value() * 1000);
    });
    connect(ui->sl_speed, &QSlider::valueChanged, this,
            [=]() { emit ui->sl_speed->sliderReleased(); });
    connect(ui->pb_restart, &QPushButton::clicked, this, [this]() {
        if (!m_mdxEngin) return;
        int start = ui->sb_start->value();
        m_idx = start;
    });
    connect(ui->sb_start, QOverload<int>::of(&QSpinBox::valueChanged), this,
            [this](int v) {
                if (v > m_idx) m_idx = v;
        MSettings::setValue("coca/low", v);
            });
    connect(ui->sb_end, QOverload<int>::of(&QSpinBox::valueChanged), this,
            [this](int v) {
                if (v < m_idx) {
                    m_idx = ui->sb_start->value();
                }
                MSettings::setValue("coca/high", v);
            });

    // settings
    bool onoff = MSettings::value("coca/on", false);
    int interval = MSettings::value("coca/interval", 3);
    int currentIdx = MSettings::value("coca/idx", 1);
    int low = MSettings::value("coca/low", 0);
    int high = MSettings::value("coca/high", 50000);

    ui->sl_speed->setValue(interval);
    ui->sb_start->setValue(low);
    ui->sb_end->setValue(high);
    ui->lb_idx->setNum(currentIdx);
    m_idx = currentIdx;


    connect(sb, &BoundarySwitchBase::stateChanged, this, [this](bool st){
        MSettings::setValue("coca/on", st);
        if (st) {
            m_enTimer->start(ui->sl_speed->value() * 1000);
        } else {
            m_enTimer->stop();
        }
    });
    sb->setType(3);
    sb->setState(onoff);

    BezierWave* wave = new BezierWave(ui->w_progress);
    QVBoxLayout* lo = new QVBoxLayout(ui->w_progress);
    lo->addWidget(wave);
    lo->addWidget(ui->lb_idx);
}

void WordFrame::initCsh() {
    CheckBox1* cb1 = new CheckBox1(ui->gb_csh);
    CheckBox1* cb2 = new CheckBox1(ui->gb_csh);
    CheckBox1* cb3 = new CheckBox1(ui->gb_csh);
    ui->lo_csh->addWidget(cb1);
    ui->lo_csh->addWidget(cb2);
    ui->lo_csh->addWidget(cb3);
    cb1->setText("一级-3500");
    cb2->setText("二级-3000");
    cb3->setText("三级-1605");
    // cb1->setStyleSheet("font-size: 30px;");



    connect(cb1, &QCheckBox::clicked, this, [this](bool checked) {
        MSettings::setValue("csh/L1", checked);
        if (m_L1.isEmpty()) {
            QFile f(":/Res/csh/L1.txt");
            if (f.open(QIODevice::ReadOnly)) {
                QTextStream ifstream(&f);
                while (!ifstream.atEnd()) m_L1.append(f.readLine().trimmed());
            }
            genRandVector(m_L1);
        }
        if (checked) {
            m_tidL1 = startTimer(2000);
        } else {
            if (m_tidL1 < 0) return;
            killTimer(m_tidL1);
        }
    });
    connect(cb2, &QCheckBox::clicked, this, [this](bool checked) {
        MSettings::setValue("csh/L2", checked);
        if (m_L2.isEmpty()) {
            QFile f(":/Res/csh/L2.txt");
            if (f.open(QIODevice::ReadOnly)) {
                QTextStream ifstream(&f);
                while (!ifstream.atEnd()) m_L2.append(f.readLine().trimmed());
            }
            genRandVector(m_L2);
        }
        if (checked) {
            m_tidL2 = startTimer(2000);
        } else {
            if (m_tidL2 < 0) return;
            killTimer(m_tidL2);
        }
    });
    connect(cb3, &QCheckBox::clicked, this, [this](bool checked) {
        MSettings::setValue("csh/L3", checked);
        if (m_L3.isEmpty()) {
            QFile f(":/Res/csh/L3.txt");
            if (f.open(QIODevice::ReadOnly)) {
                QTextStream ifstream(&f);
                while (!ifstream.atEnd()) m_L3.append(f.readLine().trimmed());
            }
            genRandVector(m_L3);
        }
        if (checked) {
            m_tidL3 = startTimer(4000);
        } else {
            if (m_tidL3 < 0) return;
            killTimer(m_tidL3);
        }
    });
    // csh
    bool l1 = MSettings::value("csh/L1", false);
    bool l2 = MSettings::value("csh/L2", false);
    bool l3 = MSettings::value("csh/L3", false);
    cb1->setChecked(l1);
    cb2->setChecked(l2);
    cb3->setChecked(l3);
}

void WordFrame::getUnknownWord(const QString& file) {
    QVector<QString> lines;
    QFile f(":/Res/rank.csv");
    if (f.open(QIODevice::ReadOnly)) {
        QTextStream ifstream(&f);
        while (!ifstream.atEnd()) lines.append(f.readLine().trimmed());
    }

    QSet<QString> knownlist;
    QFile ifknown(KNOWN);
    if (ifknown.open(QIODevice::ReadOnly)) {
        QTextStream ifstream(&ifknown);
        while (!ifstream.atEnd()) {
            knownlist.insert(ifknown.readLine().trimmed());
        }
    }

    for (auto& line : lines) {
        if (!knownlist.contains(line)) m_cocas.append(line);
    }
}

void WordFrame::genRandVector(QVector<QString>& vs) {
    // 2. 打乱索引
    std::mt19937 rng(QRandomGenerator::global()->generate());  // 真随机种子
    std::shuffle(vs.begin(), vs.end(), rng);
}

void WordFrame::timerEvent(QTimerEvent* event) {
    static int l1 = 0, l2 = 0, l3 = 0;
    int id = event->timerId();
    QString hanz = "";
    if (id == m_tidL1) {
        // qDebug() << l1 <<  m_L1[l1];
        hanz = m_L1[l1];
        l1++;
    } else if (id == m_tidL2) {
        hanz = m_L2[l2];
        l2++;
    } else if (id == m_tidL3) {
        hanz = m_L3[l3];
        l3++;
    }

    FlyWidget* fw = new FlyWidget(hanz, nullptr);
    fw->show();
}

void WordFrame::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    dm_bg->draw(painter);
    QWidget::paintEvent(event);
}

WordFrame::~WordFrame() {
    delete ui;
    if (m_mdxEngin) delete m_mdxEngin;
    MSettings::setValue("coca/idx", m_idx);
}

void WordFrame::genWord() {
    QString word = "hello";
    if (!m_mdxEngin) return;
    word = next();
    FlyWidget* fw = new FlyWidget(word, nullptr);
    connect(fw, &FlyWidget::clicked, m_lookup,
            [this](QString msg, int t, QPoint p) {
                if (t == FlyWidget::LinkClick) {
                    return;
                }
                msg = m_mdxEngin->query(msg);
                m_lookup->moveAndExplain(msg, t, p);
            });
    fw->show();
}

QString WordFrame::next() {
    if (m_idx >= m_cocas.size()) return "\n\n";
    if(m_idx > ui->sb_end->value()) m_idx = ui->sb_start->value();
    auto ret = m_cocas.at(m_idx);
    m_idx++;
    return ret;
}
